package org.zero.onlinesubject.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mysql.cj.util.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.zero.onlinesubject.common.constant.RedisConstant;
import org.zero.onlinesubject.common.vo.HomeworkVo;
import org.zero.onlinesubject.common.vo.LiveRoomVo;
import org.zero.onlinesubject.common.vo.Result;
import org.zero.onlinesubject.common.vo.WxUserInfo;
import org.zero.onlinesubject.common.vo.components.*;
import org.zero.onlinesubject.entity.Homework;
import org.zero.onlinesubject.entity.LiveRoom;
import org.zero.onlinesubject.entity.SystemFile;
import org.zero.onlinesubject.entity.User;
import org.zero.onlinesubject.handler.MediaConvertHandler;
import org.zero.onlinesubject.mapper.CourseMapper;
import org.zero.onlinesubject.mapper.HomeworkMapper;
import org.zero.onlinesubject.mapper.SystemFileMapper;
import org.zero.onlinesubject.mapper.UserMapper;
import org.zero.onlinesubject.service.LiveRoomService;
import org.zero.onlinesubject.service.UserService;
import org.zero.onlinesubject.utils.UserContextHolder;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

@Component
public class ThreadService {

    private final Map<String,String> liveStateMap = new HashMap<>();

    @Resource
    private PlatformTransactionManager transactionManager;

    @PostConstruct
    private void initMap(){
        liveStateMap.put("0001","未开始");
        liveStateMap.put("0002","进行中");
        liveStateMap.put("0003","已结束");
    }

    @Async("taskExecutor")
    public void saveUserInfo(UserService userService, User user){
        // 判断用户在数据库中是否存在
        boolean flag = userService.exists(new QueryWrapper<User>().eq("UserID", user.getUserid()));
        if(flag){
            return;
        }
        // 不存在则添加到数据库中
        userService.save(user);
    }

    @Async("taskExecutor")
    public void updateCourseViewCount(CourseMapper courseMapper, String courseId) {
        courseMapper.updateViewCount(courseId);
    }

    @Async("taskExecutor")
    public void updateCourseLikeCount(CourseMapper courseMapper,String courseId) {
        courseMapper.updateLikeCount(courseId);
    }

    @Async("taskExecutor")
    public void addLiveRoomCache(StringRedisTemplate stringRedisTemplate, LiveRoom room, String userId) {
        String body = stringRedisTemplate.opsForValue().get(RedisConstant.LIVE_ROOM_USER + userId);
        if(StringUtils.isNullOrEmpty(body)) return;
        List<LiveRoom> liveRooms = JSON.parseObject(body, new TypeReference<List<LiveRoom>>() {});
        liveRooms.add(room);
        stringRedisTemplate.opsForValue().set(RedisConstant.LIVE_ROOM_USER+userId,JSON.toJSONString(liveRooms),2, TimeUnit.MINUTES);
    }

    @Async("taskExecutor")
    public void updateLiveRoomCache(StringRedisTemplate stringRedisTemplate,String userId,String liveId, String liveState) {
        String body = stringRedisTemplate.opsForValue().get(RedisConstant.LIVE_ROOM_USER + userId);
        if(StringUtils.isNullOrEmpty(body)) return;
        List<LiveRoomVo> liveRoomVos = JSON.parseObject(body, new TypeReference<List<LiveRoomVo>>() {});
        liveRoomVos.parallelStream().forEach(vo->{
            if(vo.getLiveid().equals(liveId)){
                vo.setLivestate(liveStateMap.get(liveState));
            }
        });
        stringRedisTemplate.opsForValue().set(RedisConstant.LIVE_ROOM_USER+userId,JSON.toJSONString(liveRoomVos),30, TimeUnit.MINUTES);
    }

    @Async("taskExecutor")
    public void dispatchHomework(HomeworkVo homeworkVo, HomeworkMapper homeworkMapper, UserMapper userMapper) throws ExecutionException, InterruptedException, TimeoutException {
        String clsID = homeworkVo.getClassId();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("ClassID",clsID);
        List<User> users = userMapper.selectList(wrapper);
        if(users.size()==0) return;
        List<String> userIds = users.stream().map(User::getUserid).collect(Collectors.toList());

        List<SingleSelect> singleList = homeworkVo.getSingleList();
        List<MultiSelect> multiList = homeworkVo.getMultiList();
        List<FillBlank> fillBlankList = homeworkVo.getFillBlankList();
        List<ShortAnswerQuestion> questionList = homeworkVo.getShortAnswerList();

        CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {
            singleList.forEach(item -> {
                item.setChoice(null);
                Node[] nodes = item.getNodes();
                for (int i = 0; i < nodes.length; i++) {
                    nodes[i].setIsSelect(false);
                }
            });
        });
        CompletableFuture<Void> f2 = CompletableFuture.runAsync(() -> {
            multiList.forEach(item -> {
                Node[] nodes = item.getNodes();
                for (int i = 0; i < nodes.length; i++) {
                    nodes[i].setIsSelect(false);
                }
            });
        });
        CompletableFuture<Void> f3 = CompletableFuture.runAsync(() -> {
            fillBlankList.forEach(item -> {
                item.setAnswer("");
            });
        });
        CompletableFuture<Void> f4 = CompletableFuture.runAsync(() -> {
            questionList.forEach(item -> {
                item.setAnswer("");
            });
        });

        CompletableFuture.allOf(f1,f2,f3,f4).get(3,TimeUnit.SECONDS);

        List<Homework> homeworkList = new ArrayList<>();
        for (String userId : userIds) {
            Homework homework = new Homework();
            homework.setRecevieId(userId);
            homework.setApprovalState("0000");
            copyProperty(homeworkVo,homework);
            homeworkList.add(homework);
        }

        TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        int rows = homeworkMapper.insertBatch(homeworkList);
        if(rows != userIds.size()){
            transactionStatus.setRollbackOnly();
            transactionManager.rollback(transactionStatus);
            throw new RuntimeException("批量插入数据失败");
        }else{
            transactionManager.commit(transactionStatus);
        }
    }

    public void copyProperty(HomeworkVo homeworkVo,Homework homework){
        homework.setName(homeworkVo.getName());
        homework.setFromcode(homeworkVo.getId());
        homework.setSenderId(homeworkVo.getSender());
        homework.setFromcode(homeworkVo.getId());
        homework.setCourseId(homeworkVo.getCourseId());
        homework.setClassId(homeworkVo.getClassId());
        homework.setScore(homeworkVo.getTotalScore());

        homework.setSingleList(JSON.toJSONString(homeworkVo.getSingleList()));
        homework.setMultiList(JSON.toJSONString(homeworkVo.getMultiList()));
        homework.setFillBlankList(JSON.toJSONString(homeworkVo.getFillBlankList()));
        homework.setShortAnswerList(JSON.toJSONString(homeworkVo.getShortAnswerList()));

        homework.setIsFinished(homeworkVo.getIsFinished());
        homework.setQuestionCount(homeworkVo.getQuestionCount());
        homework.setPubTime(homeworkVo.getPubTime());
    }

    @Async("taskExecutor")
    public void webm2MP4(String sourceFile,String destFile, String bizId,SystemFileMapper systemFileMapper) {
        String cmd = "-i " + sourceFile + " -preset fast -b:v 1M -crf 22 -threads 8 -y " + destFile;;
        MediaConvertHandler.executeCmd(cmd);

        UpdateWrapper<SystemFile> wrapper = new UpdateWrapper<>();
        wrapper.set("IsFinished",true).eq("BizID",bizId);
        systemFileMapper.update(wrapper);
    }

    @Async("taskExecutor")
    public void removeMsgCache(List<String> uids,StringRedisTemplate stringRedisTemplate) {
        uids.forEach(uid->{
            stringRedisTemplate.delete(RedisConstant.MESSAGE_PREFIX+uid);
        });
    }

    public void deleteCourseCache(StringRedisTemplate stringRedisTemplate,String courseId, String userId) {
        stringRedisTemplate.delete(RedisConstant.COURSE_CHAPTER_PREFIX + courseId);
        stringRedisTemplate.delete(RedisConstant.CHAPTER_VIDEO_PREFIX + courseId);
        stringRedisTemplate.delete(RedisConstant.CHAPTER_VIDEO_ID_PREFIX + courseId);
        stringRedisTemplate.delete(RedisConstant.COURSE_INFO_PREFIX + courseId);
        stringRedisTemplate.delete(RedisConstant.USER_COURSE_NAME + userId);
    }
}